<?php
	
	namespace Aspic\Session;
	
	use Aspic as A;
	use Aspic\File\File;
	
	/**
	* DbSession class store session in Database
	* 
	* Session table columns are the same as Session class options
	*/
	class DbSession extends AbstractSession {
		const SESSIONS_DATA_FILE_NAME = 'sessions.data';
	
		protected $db;
		protected $sessionTable;
		protected $configTable;
		
		public function __construct(A\Database\QueryExecuterInterface $db, $lifeTime = 86400, array $options = array()) {
			// because in destruct the CU (current directory is not the same as in others methods see php doc)
			
			$this->db = $db;
			
			$defaultOptions = array(
				'sessionTable' => 'session', 
				'configTable' => 'config', // use to store last clean time
				'configNameColumn' => 'name',
				'configName' => 'sessionCleanTime', // The option name in the table
				'configValueColumn' => 'value', 
			);
			
			$options = array_merge($defaultOptions, $options);
			
			parent::__construct($lifeTime, $options);
			
			$this->initDbTables();
		}
		
		protected function initDbTables() {
			$tableClass = 'Aspic\\Database\\'.$this->db->getDbType(true).'\\Table';
			
			$this->sessionTable = new $tableClass($this->opt('sessionTable'), 'id', array(
				'id', 
				'creationTime', 
				'ip', 
				'navigator', 
				'acceptLanguages', 
				'data', 
			), $this->db);
			
			$this->configTable = new $tableClass($this->opt('configTable'), $this->opt('configNameColumn'), array(
				$this->opt('configNameColumn'), 
				$this->opt('configValueColumn'), 
			), $this->db);
			
		}
		
		############### READ / WRITE METHODS ##########################
		
		protected function saveSession($id, $data) {
			$data['data'] = serialize($data['data']);
			$data['id'] = $id;
		
			if($this->sessionIdExists($id)) {
				$this->sessionTable->updateRow($id, $data);
			}
			else {
				$this->sessionTable->insert($data);
			}
		}
		
		protected function getSessionData($id) {
			$session = $this->sessionTable->find($id);
			
			if($session) {					
				$session->data = unserialize($session->data);
				$sessArr = (array)$session;
				
				return $sessArr;
			}
			else {
				throw new Exception('Session file with id: "'.$id.'" does not exist');
			}
		}
		
		/**
		* Remove a session
		*/
		protected function removeSession($id) {
			$this->sessionTable->delete($id);
		}
		
		protected function getAllSessions() {
			$sessions = $this->sessionTable->fetchAll();
			
			return $sessions;
		}
		
		
		/**
		* Check if it is time to clean session folder (or other storage way)
		*/
		protected function checkClean() {
			if(!is_null($this->cleanInterval)) {
				$lastCleanData = $this->configTable->find($this->opt('configNameColumn'));
				
				if(!$lastCleanData) {
					$this->configTable->insert(array(
						$this->opt('configNameColumn') => $this->opt('configName'), 
						$this->opt('configValueColumn') => time()
					));
				}
				else {
					$lastClean = $lastCleanData[$this->opt('configValueColumn')];
					
					if(($lastClean + $this->cleanInterval) <= time()) {
					
						$this->configTable->updateRow(array(
							$this->opt('configNameColumn') => $this->opt('configName'), 
							$this->opt('configValueColumn') => time()
						));
						
						$this->clean();
					}
				}
			}
		}
		
		protected function sessionIdExists($id) {
			return $this->sessionTable->exists(array('id' => $id));
		}
		
	}
	
?>